﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;

namespace WoChu.CF.BaseFrame.Json
{
   /// <summary>
   /// JSON 格式拼接器.
   /// </summary>
    public class JsonWriter : IDisposable 
    {
        private bool _disposed;
        private const int _indentationSpaces = 2;
        private int _currentIndentation;
        private readonly TextWriter _writer;
         
        #region construct function...
        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        public JsonWriter(TextWriter output)
        {
            _writer = output;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        public JsonWriter(Stream output) : this(new StreamWriter(output, Encoding.UTF8)){}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="file"></param>
        public JsonWriter(string file) : this(new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read)){}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="output"></param>
        public JsonWriter(StringBuilder output) : this(new StringWriter(output, CultureInfo.InvariantCulture)){}
        #endregion 

        
        public virtual void WriteNull()
        {
            WriteRaw(JsonTokens.NULL_STRING);            
        }
        public virtual void WriteString(string value)
        {
            _writer.Write(string.Concat(JsonTokens.STRING_DELIMITER, value.Replace("\"", "\\\""), JsonTokens.STRING_DELIMITER));
        }
        public virtual void WriteRaw(string value)
        {
            _writer.Write(value);
        }
        public virtual void WriteChar(char value)
        {
            WriteString(value.ToString());
        }
        public virtual void WriteBool(bool value)
        {
            WriteRaw(value ? "true" : "false");
        }
        public virtual void WriteDate(DateTime date)
        {
            WriteString(date.ToString("G", CultureInfo.InvariantCulture));
        }
        public virtual void WriteKey(string key)
        {
            Indent();
            WriteString(key);
            _writer.Write(JsonTokens.PAIR_SEPARATOR);
        }

        public virtual void BeginObject()
        {
            NewLineAndIndent();
            _writer.Write(JsonTokens.START_OBJECT_LITERAL_CHARACTER);
            NewLine();
            _currentIndentation += 1;
        }
        public virtual void EndObject()
        {
            NewLine();
            _currentIndentation -= 1;
            Indent();
            _writer.Write('}');
        }
        public virtual void EndArray()
        {
            _writer.Write(JsonTokens.END_ARRAY_CHARACTER);
        }
        public virtual void BeginArray()
        {
            _writer.Write(JsonTokens.START_ARRAY_CHARACTER);
        }
        public virtual void SeparateElements()
        {
            _writer.Write(JsonTokens.ELEMENT_SEPARATOR);
        }

        [Conditional("DEBUG")]
        public virtual void NewLineAndIndent()
        {
            NewLine();
            Indent();
        }
        [Conditional("DEBUG")]
        public virtual void Indent()
        {
            _writer.Write(new string(' ', _indentationSpaces * _currentIndentation));
        }
        [Conditional("DEBUG")]
        public virtual void NewLine()
        {
           // _writer.Write('\n');
        }

        public void Flush()
        {
            _writer.Flush();
        }
        public void Dispose()
        {
            Dispose(true);            
            GC.SuppressFinalize(this);
        }
        private void Dispose(bool disposing)
        {            
            if (!_disposed)
            {                
                if (disposing)
                {
                    Flush();                    
                    _writer.Close();
                }                
                _disposed = true;
            }
        }
    }
}
